package king.dominic.jorc.core;

import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.text.TextUtils;

import com.googlecode.leptonica.android.GrayQuant;
import com.googlecode.leptonica.android.Pix;
import com.googlecode.leptonica.android.ReadFile;
import com.googlecode.tesseract.android.TessBaseAPI;

import java.lang.ref.WeakReference;

import king.dominic.jlibrary.util.BitmapUtils;

/**
 * Created by DominicKing on 2017/10/26.
 * GetUTF8TextAsyncTask
 */

class GetUTF8TextAsyncTask extends AsyncTask<OCR.RecycledBitmap, Integer, Object> {
    private boolean isBack;
    private WeakReference<TessBaseAPI> apiWeakReference;
    private WeakReference<Listener.Callback<Object>> callbackWeakReference;

    private GetUTF8TextAsyncTask(Builder builder) {
        apiWeakReference = builder.apiWeakReference;
        callbackWeakReference = builder.callbackWeakReference;
        this.isBack = builder.isBack;
    }

    @Override
    protected Object doInBackground(OCR.RecycledBitmap... params) {
        TessBaseAPI api = apiWeakReference.get();
        if (api == null) return ErrorCode.API_NOT_INIT;
        OCR.RecycledBitmap recycledBitmap = params[0];
        if (recycledBitmap.isUseless()) return ErrorCode.BITMAP_USELESS;


        IdentityCard card = new IdentityCard();
        final Bitmap bitmap = recycledBitmap.bitmap;

        final Rect rect = recycledBitmap.rect;

        api.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "");

        if (isBack) {

            if (!TextUtils.equals(get(api, bitmap, Bounds.title(rect)), "中华人民共和国"))
                return ErrorCode.NOT_FOUND_TITLE;
            api.clear();

            Bitmap b = BitmapUtils.crop(bitmap, Bounds.visaOffice(rect));
            Pix pix = ReadFile.readBitmap(b);
            Pix p = GrayQuant.pixThresholdToBinary(pix, 62);
            pix.recycle();
            api.setImage(p);
            p.recycle();
            b.recycle();
            final String text =api.getUTF8Text().replaceAll("\r", "").replaceAll("\t", "").replaceAll("\n", "").replaceAll(" ", "").trim();
            if(TextUtils.isEmpty(text) || api.meanConfidence() < 72) return ErrorCode.NOT_FOUND_VISA_OFFICE;
            card.setVisaOffice(text);
            api.clear();
        } else {
            card.setName(get(api, bitmap, Bounds.name(rect)));
            if (TextUtils.isEmpty(card.getName()) || api.meanConfidence() < 80) return ErrorCode.NOT_FOUND_NAME;
            api.clear();

            card.setAddress(get(api, bitmap, Bounds.address(rect)));
            if (TextUtils.isEmpty(card.getAddress()) || api.meanConfidence() < 80) return ErrorCode.NOT_FOUND_ADDRESS;
            api.clear();

            api.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "男女");
            card.setSex(get(api, bitmap, Bounds.sex(rect)));
            if (TextUtils.isEmpty(card.getSex()) || api.meanConfidence() < 80) return ErrorCode.NOT_FOUND_SEX;
            api.clear();

            api.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "0123456789年月日");
            card.setBirthday(get(api, bitmap, Bounds.birthday(rect)));
            if (TextUtils.isEmpty(card.getBirthday()) || api.meanConfidence() < 80) return ErrorCode.NOT_FOUND_BIRTHDAY;
            api.clear();

            api.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "0123456789X");
            card.setId(get(api, bitmap, Bounds.number(rect)));
            if (TextUtils.isEmpty(card.getId()) || api.meanConfidence() < 60) return ErrorCode.NOT_FOUND_NUMBER;
            api.clear();
        }
        recycledBitmap.autoRecycled();

        return card;
    }

    private static String get(TessBaseAPI api, Bitmap bitmap, Rect bounds) {
        Bitmap b = BitmapUtils.crop(bitmap, bounds);
        final String text = getText(api, b).replaceAll("\r", "").replaceAll("\t", "").replaceAll("\n", "").replaceAll(" ", "").trim();
        b.recycle();
        return text;
    }

    private static boolean check(TessBaseAPI api, Bitmap bitmap, Rect bounds, String name) {
        return TextUtils.equals(get(api, bitmap, bounds), name);
    }

    private static String getText(TessBaseAPI api, Bitmap bitmap) {
        api.setImage(bitmap);
        bitmap.recycle();
        return api.getUTF8Text();
    }

    @Override
    protected void onPostExecute(Object s) {
        super.onPostExecute(s);
        apiWeakReference.get().clear();
        if (callbackWeakReference != null) {
            Listener.Callback<Object> callback = callbackWeakReference.get();
            if (callback != null) callback.callback(s);
        }
        apiWeakReference.clear();
        callbackWeakReference.clear();
    }

    public static final class Builder {
        private boolean isBack = false;
        private WeakReference<TessBaseAPI> apiWeakReference;
        private WeakReference<Listener.Callback<Object>> callbackWeakReference;

        Builder(TessBaseAPI val) {
            apiWeakReference = new WeakReference<>(val);
        }

        Builder isBack(boolean isBack) {
            this.isBack = isBack;
            return this;
        }

        Builder callback(Listener.Callback<Object> val) {
            callbackWeakReference = new WeakReference<>(val);
            return this;
        }

        GetUTF8TextAsyncTask build() {
            return new GetUTF8TextAsyncTask(this);
        }
    }

}
